package com.zhonglz.service.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.zhonglz.commons.base.BaseService;
import com.zhonglz.mapper.SysFileShiftMapper;
import com.zhonglz.model.SysFileInfo;
import com.zhonglz.model.SysFileShift;
import com.zhonglz.service.SysFileInfoService;
import com.zhonglz.util.Constans;
import com.zhonglz.util.base64.Base64Utils;
import com.zhonglz.util.file.FileConversionUtils;
import com.zhonglz.util.minio.MinioUtils;
import com.zhonglz.util.result.ResultUtils;
import com.zhonglz.util.tools.ObjectUtils;
import com.zhonglz.util.tools.UuidUtils;

/***
 * 文件信息接口实现类
 * @author zhonglz
 * @date 2020年7月28日
 */
@Service
@Transactional 
public class SysFileInfoServiceImpl extends BaseService implements SysFileInfoService {
	private static Logger logger = LoggerFactory.getLogger(SysFileInfoServiceImpl.class);


	/***
	 * 分页查询
	 */
	@Override
	public List<SysFileInfo> selectByDataList(Map<String, Object> mapParam) {
		return sysFileInfoMapper.selectByDataList(mapParam);
	}
	
	/***
	 *  uploadFile 
	 *  上传一个文件到服务器并返回uuid
	 *  仅支持word、图片和pdf三种格式
	 *  最后返回的文件统一转换为pdf
	 */
	@Override
	public ResultUtils uploadFile(MultipartFile file) {
		ResultUtils result=new ResultUtils();
		SysFileInfo info=new SysFileInfo();
		//文件id 
		String  fileUid=UuidUtils.uuid();
		info.setFileUid(fileUid);
		logger.info("文件UUID:"+fileUid);
		//文件真实名
		String fileRealName = file.getOriginalFilename();
		info.setFileRealName(fileRealName);
		logger.info("文件真实名："+fileRealName);
		//文件后缀名
		String fileSuffix = fileRealName.substring(fileRealName.lastIndexOf("."));//文件后缀
		info.setFileSuffix(fileSuffix);
		logger.info("文件后缀名："+fileSuffix);
		//文件存储名
		String fileStoreName = fileUid+fileSuffix; 
		info.setFileStoreName(fileStoreName);
		logger.info("文件存储名："+fileStoreName);
//		//文件存储临时名称
//		String fileTempName=fileUid+fileSuffix;
		//文件大小
		long fileSize=file.getSize();
		info.setFileSize(fileSize);
		logger.info("文件大小："+fileSize);
		info.setCreateTime(new Date());
		try {
			//直接上传
			String fileAddress = sysBaseSetService.baseSetValue(Constans.MINIO_PATH) +"/"+ fileStoreName;
			logger.info("文件存储地址："+fileAddress);
			info.setFileAddress(fileAddress);
			
			InputStream inputStream = file.getInputStream();
			MinioUtils.putObject(fileAddress, inputStream);
			inputStream.close();
			if(sysFileInfoMapper.insertSelective(info)>0){
				result.setCode(ResultUtils.CODE_SUCCESS);
				result.setMsg("操作成功");
				Map<String, Object> resultMap = new HashMap<String, Object>();
				String filePath = MinioUtils.getObjectUrl(fileAddress);
				resultMap.put("filePath", filePath);
				resultMap.put("fileUuid", fileUid);
				result.setObject(resultMap);
			}else{
				result.setCode(ResultUtils.CODE_ERROR);
				result.setMsg("文件上传失败");
				return result;
			}
		} catch (Exception e){
			e.printStackTrace();
			result.setCode(ResultUtils.CODE_EXCEPTION);
			result.setMsg("文件上传出错");
			return result;
		}
		
		return result;
	}

	/***
	 *  uploadFile 
	 *  上传一个文件到服务器并返回uuid
	 * @param fileUid 文件Uid
	 * @param fileRealName 文件真实名
	 * @param fileSuffix 文件后缀
	 * @param is 文件流
	 * @return
	 */
	@Override
	public ResultUtils uploadFile(String fileUuid,String fileRealName, String fileSuffix, InputStream is) {
		ResultUtils result=new ResultUtils();
		SysFileInfo info=new SysFileInfo();
		//文件UUid 
		info.setFileUid(fileUuid);
		logger.info("文件UUID:"+fileUuid);
		//文件真实名
		info.setFileRealName(fileRealName);
		logger.info("文件真实名："+fileRealName);
		//文件后缀名
		info.setFileSuffix(fileSuffix);
		logger.info("文件后缀名："+fileSuffix);
		//文件存储名
		String fileStoreName = fileUuid+fileSuffix; 
		info.setFileStoreName(fileStoreName);
		logger.info("文件存储名："+fileStoreName);
		//文件大小
		long fileSize = 0;
		try {
			fileSize = is.available();
		} catch (Exception e1) {
			e1.printStackTrace();
			fileSize=0;
		}
		info.setFileSize(fileSize);
		logger.info("文件大小："+fileSize);
		info.setCreateTime(new Date());
		//文件存储地址
		String fileAddress;
		if(fileSuffix.equals(".pfx")){//判断是否为证书类型
			fileAddress=sysBaseSetService.baseSetValue(Constans.MINIO_CERT_PATH) +"/"+ info.getFileStoreName();
		}else{
			fileAddress=sysBaseSetService.baseSetValue(Constans.MINIO_PATH) +"/"+ info.getFileStoreName();
		}
		info.setFileAddress(fileAddress);//添加文件存储位置
		try {
			MinioUtils.putObject(fileAddress, is);
			if(sysFileInfoMapper.insertSelective(info)>0){
				result.setCode(ResultUtils.CODE_SUCCESS);
				result.setMsg("操作成功");
				Map<String, Object> resultMap = new HashMap<String, Object>();
				String filePath = MinioUtils.getObjectUrl(fileAddress);
				resultMap.put("filePath", filePath);
				resultMap.put("fileUuid", fileUuid);
				result.setObject(resultMap);
			}else{
				result.setCode(ResultUtils.CODE_ERROR);
				result.setMsg("文件上传失败");
				return result;
			}
		} catch (Exception e) {
			result.setCode(ResultUtils.CODE_EXCEPTION);
			result.setMsg("文件上传出错");
			return result;
		}
		return result;
	}
	
	@Override
	public ResultUtils uploadFileToBase(String imgBase64Str) {
		try {
		String subBase = imgBase64Str.substring(imgBase64Str.indexOf(",") + 1);// 去掉base64字符串的开头部分
		// 将字符串转换为byte数组
		byte[] bytes;
		bytes = Base64Utils.decode(subBase.trim());
		for (int i = 0; i < bytes.length; ++i) {
			if (bytes[i] < 0) {// 调整异常数据
				bytes[i] += 256;
			}
		}
		String fileSuffix=getFileExtendName(bytes);
		//转化为输入流
		ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
		ResultUtils result=new ResultUtils();
		String fileUid = UuidUtils.uuid();
		SysFileInfo info=new SysFileInfo();
		//文件UUid 
		info.setFileUid(fileUid);
		logger.info("文件UUID:"+fileUid);
		//文件名
		String fileName = fileUid+fileSuffix;
		//文件真实名
		info.setFileRealName(fileName);
		logger.info("文件真实名："+fileName);
		//文件后缀名
		info.setFileSuffix(fileSuffix);
		logger.info("文件后缀名："+fileSuffix);
		//文件存储名
		info.setFileStoreName(fileName);
		String filePath = sysBaseSetService.baseSetValue(Constans.MINIO_PATH) +"/"+ fileName;
		//添加文件存储位置
		info.setFileAddress(filePath);
		info.setCreateTime(new Date());
		//上传文件
		MinioUtils.putObject(filePath, inputStream);
		if(sysFileInfoMapper.insertSelective(info)>0){
			result.setCode(ResultUtils.CODE_SUCCESS);
			result.setMsg("上传成功");
			result.setObject(fileUid);
		}else{
			result.setCode(ResultUtils.CODE_ERROR);
			result.setMsg("文件上传失败");
		}

		return result;
		
		} catch (Exception e){
			e.printStackTrace();
			return new ResultUtils(ResultUtils.CODE_EXCEPTION, "发生异常");
		}
	}
	
	

	@Override
	public ResultUtils uploadFile(String fileUid, String fileRealName, String filePath, String fileSuffix) {
		ResultUtils result=new ResultUtils();
		SysFileInfo info=new SysFileInfo();
		//文件UUid 
		info.setFileUid(fileUid);
		logger.info("文件UUID:"+fileUid);
		//文件真实名
		info.setFileRealName(fileRealName);
		logger.info("文件真实名："+fileRealName);
		//文件后缀名
		info.setFileSuffix(fileSuffix);
		logger.info("文件后缀名："+fileSuffix);
		//文件存储名
		info.setFileStoreName(fileRealName);
		//添加文件存储位置
		info.setFileAddress(filePath);
		info.setCreateTime(new Date());
		if(sysFileInfoMapper.insertSelective(info)>0){
			result.setCode(ResultUtils.CODE_SUCCESS);
			result.setMsg("操作成功");
			result.setObject(fileUid);
		}else{
			result.setCode(ResultUtils.CODE_ERROR);
			result.setMsg("文件上传失败");
		}
		return result;
		
	}
	
	@Override
	public int uploadFileInfo(String fileUid, String fileRealName, String filePath, String fileSuffix) {
		ResultUtils result=new ResultUtils();
		SysFileInfo info=new SysFileInfo();
		//文件UUid 
		info.setFileUid(fileUid);
		logger.info("文件UUID:"+fileUid);
		//文件真实名
		info.setFileRealName(fileRealName);
		logger.info("文件真实名："+fileRealName);
		//文件后缀名
		info.setFileSuffix(fileSuffix);
		logger.info("文件后缀名："+fileSuffix);
		//文件存储名
		info.setFileStoreName(fileRealName);
		//添加文件存储位置
		info.setFileAddress(filePath);
		info.setCreateTime(new Date());
		return sysFileInfoMapper.insertSelective(info);
		
	}

	@Override
	public ResultUtils selectFileByUid(String fileUid) {
		ResultUtils result=new ResultUtils();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("fileUid", fileUid);
		SysFileInfo info = sysFileInfoMapper.selectByDataInfo(map);
		if (ObjectUtils.isNotEmpty(info)) {
			result.setCode(ResultUtils.CODE_SUCCESS);
			result.setMsg("查询成功");
			result.setObject(info);
		}else{
			result.setCode(ResultUtils.CODE_ERROR);
			result.setMsg("没有找到记录");
		}
		return result;
	}
	
	/***
	 * getFileExtendName  根据base64转换的byte值  得到文件的后缀
	 * @param photoByte
	 * @return
	 */
	public String getFileExtendName(byte[] photoByte) {
		String strFileExtendName = ".jpg";
		if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70)
				&& (photoByte[3] == 56) && ((photoByte[4] == 55) || (photoByte[4] == 57))
				&& (photoByte[5] == 97)) {
			strFileExtendName = ".gif";
		} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73)
				&& (photoByte[9] == 70)) {
			strFileExtendName = ".jpg";
		} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
			strFileExtendName = ".bmp";
		} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
			strFileExtendName = ".png";
		}
		return strFileExtendName;
	}
	
	/**
	 * 文件转换
	 */
	@Override
	public ResultUtils fileToPdf(SysFileInfo sysFileInfo) {
		try {
			SysFileInfo pdfFileInfo = new SysFileInfo();
			//源文件的地址
			String fileAddress = sysFileInfo.getFileAddress();
			//后缀
			String fileSuffix = sysFileInfo.getFileSuffix();
			//存储的路径
			String minio_path = sysBaseSetService.baseSetValue(Constans.MINIO_PATH);
			//生成pdf的文件名
			String pdfName = UuidUtils.uuid();
			//合成pdf文件的文件正式路径
			String pdfAddress = minio_path+"/"+pdfName+".pdf";
			//判断是word还是图片 转换成pdf 并保存在minio
			if(fileSuffix.equals(".doc") || fileSuffix.equals(".docx") ) {
				boolean flag = FileConversionUtils.wordToPdfEx(fileAddress, pdfAddress);
				if(!flag) return new ResultUtils(ResultUtils.CODE_ERROR,"word转pdf失败！");
			}else {
				return new ResultUtils(ResultUtils.CODE_ERROR,"暂未开放image转pdf功能，敬请期待！");
				// boolean flag = FileConversionUtils.imageToPdEx(fileAddress, pdfAddress);
				// if(!flag) return new ResultUtils(ResultUtils.CODE_ERROR,"imge转pdf失败！");
			}
			//保存pdf信息
			pdfFileInfo.setCreateTime(new Date());
			pdfFileInfo.setFileAddress(pdfAddress);
			pdfFileInfo.setFileRealName(pdfName+".pdf");
			pdfFileInfo.setFileSuffix(".pdf");
			pdfFileInfo.setFileUid(pdfName);
			pdfFileInfo.setFileStoreName(pdfName+".pdf");
			//获取文件大小
			InputStream pdfIn = MinioUtils.getObject(pdfAddress);
			pdfFileInfo.setFileSize((long)pdfIn.available());
			int saveFlag = sysFileInfoMapper.insert(pdfFileInfo);
			if( 0 >= saveFlag) return new ResultUtils(ResultUtils.CODE_ERROR,"保存pdf信息失败！");
			SysFileShift sysFileShift = new SysFileShift();
			sysFileShift.setShiftBackFileSuffix(pdfFileInfo.getFileSuffix());
			sysFileShift.setShiftFrontFileSuffix(fileSuffix);
			sysFileShift.setCreateTime(new Date());
			sysFileShift.setShiftStatus(Constans.FILE_TO_PDF_SUCESS);
			sysFileShift.setShiftBackFileId(pdfName);
			sysFileShift.setShiftFrontFileId(pdfFileInfo.getFileUid());
			sysFileShift.setShiftId(UuidUtils.uuid());
			int saveShift = sysFileShiftMapper.insert(sysFileShift);
			if(0 >= saveShift) return new ResultUtils(ResultUtils.CODE_ERROR,"保存转换信息失败！");
			Map returnMap = new HashMap();
			returnMap.put("orgFile", sysFileInfo);
			returnMap.put("pdfFile", pdfFileInfo);
			returnMap.put("shiftInfo", sysFileShift);
			return new ResultUtils(ResultUtils.CODE_SUCCESS,"文件转换成功！",returnMap);
		}catch (Exception e) {
			e.printStackTrace();
			return new ResultUtils(ResultUtils.CODE_EXCEPTION,"发生异常："+e.getMessage());
		}
	}

	@Override
	public ResultUtils fileConvertByType(SysFileInfo sysFileInfo, Byte type) {
		try {
			SysFileInfo pdfFileInfo = new SysFileInfo();
			//源文件的地址
			String fileAddress = sysFileInfo.getFileAddress();
			//后缀
			String fileSuffix = sysFileInfo.getFileSuffix();
			//存储的路径
			String minio_path = sysBaseSetService.baseSetValue(Constans.MINIO_PATH);
			//生成pdf的文件名
			String pdfName = UuidUtils.uuid();
			//合成pdf文件的文件正式路径
			String pdfAddress = minio_path+"/"+pdfName;
			//判断类型转换文件 并保存在minio
			String suffix = "";
			if(type == Constans.IMAGE_TO_PDF) { 
				suffix = ".pdf";
				return new ResultUtils(ResultUtils.CODE_ERROR,"imge转pdf功能暂未开放！");
				// if(!FileConversionUtils.imageToPdEx(fileAddress, pdfAddress+=suffix)) return new ResultUtils(ResultUtils.CODE_ERROR,"imge转pdf失败！");
			}else if(type == Constans.WORD_TO_PDF) {
				suffix = ".pdf";;
				if(!FileConversionUtils.wordToPdfEx(fileAddress, pdfAddress+=suffix)) return new ResultUtils(ResultUtils.CODE_ERROR,"word转pdf失败！");
			}else if(type == Constans.PDF_TO_OFD) {
				suffix = ".ofd";
				if(!FileConversionUtils.pdfToOfdEx(fileAddress, pdfAddress+=suffix)) return new ResultUtils(ResultUtils.CODE_ERROR,"pdf转ofd失败！");
			}else if(type == Constans.OFD_TO_PDF) {
				suffix = ".pdf";
				if(!FileConversionUtils.ofdToPdfEx(fileAddress, pdfAddress+=suffix)) return new ResultUtils(ResultUtils.CODE_ERROR,"ofd转pdf失败！");
			}
			//保存pdf信息
			pdfFileInfo.setCreateTime(new Date());
			pdfFileInfo.setFileAddress(pdfAddress);
			pdfFileInfo.setFileRealName(pdfName+suffix);
			pdfFileInfo.setFileSuffix(suffix);
			pdfFileInfo.setFileUid(pdfName);
			pdfFileInfo.setFileStoreName(pdfName+suffix);
			//获取文件大小
			InputStream pdfIn = MinioUtils.getObject(pdfAddress);
			pdfFileInfo.setFileSize((long)pdfIn.available());
			int saveFlag = sysFileInfoMapper.insert(pdfFileInfo);
			if( 0 >= saveFlag) return new ResultUtils(ResultUtils.CODE_ERROR,"保存文件信息失败！");
			SysFileShift sysFileShift = new SysFileShift();
			sysFileShift.setShiftBackFileSuffix(pdfFileInfo.getFileSuffix());
			sysFileShift.setShiftFrontFileSuffix(fileSuffix);
			sysFileShift.setCreateTime(new Date());
			sysFileShift.setShiftStatus(Constans.FILE_TO_PDF_SUCESS);
			sysFileShift.setShiftBackFileId(pdfName);
			sysFileShift.setShiftFrontFileId(pdfFileInfo.getFileUid());
			sysFileShift.setShiftId(UuidUtils.uuid());
			int saveShift = sysFileShiftMapper.insert(sysFileShift);
			if(0 >= saveShift) return new ResultUtils(ResultUtils.CODE_ERROR,"保存转换信息失败！");
			Map returnMap = new HashMap();
			returnMap.put("orgFile", sysFileInfo);
			returnMap.put("pdfFile", pdfFileInfo);
			returnMap.put("shiftInfo", sysFileShift);
			return new ResultUtils(ResultUtils.CODE_SUCCESS,"文件转换成功！",returnMap);
		}catch (Exception e) {
			e.printStackTrace();
			return new ResultUtils(ResultUtils.CODE_EXCEPTION,"发生异常："+e.getMessage());
		}
	}

	@Override
	public SysFileInfo selectByPrimaryKey(String sealFile) {
		return sysFileInfoMapper.selectByPrimaryKey(sealFile);
	}

}
